package com.bailian.app.controller.Apis;

import com.bailian.common.annotation.Anonymous;
import com.bailian.app.controller.BaseAppController;
import com.bailian.common.core.domain.AjaxResult;
import com.bailian.common.core.page.TableDataInfo;
import com.bailian.system.domain.BlAppointment;
import com.bailian.system.domain.vo.BlAppointmentVo;
import com.bailian.system.service.IBlAppointmentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.Map;

/**
 * 预约控制器
 * 
 * @author bailian
 */
@Api(tags = "预约相关接口")
@RestController
@RequestMapping("/app/api/appointment")
@Validated
public class AppointmentController extends BaseAppController {

    @Autowired
    private IBlAppointmentService appointmentService;

    /**
     * 预约看仓
     */
    @Anonymous
    @ApiOperation("预约看仓")
    @PostMapping("/create")
    public AjaxResult createAppointment(@Valid @RequestBody BlAppointment appointment) {
        try {
            // 获取当前用户ID（拦截器已验证token）
            Long userId = getCurrentUserId();
            
            // 检查预约日期是否为周六周日
            if (appointment.getVisitDate() != null) {
                // 将 java.util.Date 转换为 java.time.LocalDate
                LocalDate visitDate = appointment.getVisitDate().toInstant()
                    .atZone(java.time.ZoneId.systemDefault())
                    .toLocalDate();
                DayOfWeek dayOfWeek = visitDate.getDayOfWeek();
                
                if (dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY) {
                    String message = "预约日期不能选择" + getChineseDayOfWeek(dayOfWeek) + "，请选择工作日进行预约";
                    return error(message);
                }
            }
            
            // 检查预约冲突
            AjaxResult conflictCheck = checkAppointmentConflict(userId, appointment);
            if (conflictCheck != null) {
                return conflictCheck;
            }
            
            // 设置预约信息
            appointment.setUserId(userId);
            appointment.setStatus(0); // 设置默认状态为待确认
            
            // 保存预约
            int result = appointmentService.insertBlAppointment(appointment);
            
            if (result > 0) {
                return AjaxResult.success("预约成功，请等待确认", appointment);
            } else {
                return error("预约失败，请稍后重试");
            }
        } catch (Exception e) {
            logger.error("预约失败", e);
            return error("预约失败：" + e.getMessage());
        }
    }
    
    /**
     * 检查预约冲突
     */
    private AjaxResult checkAppointmentConflict(Long userId, BlAppointment newAppointment) {
        // 查询用户在该仓库的现有预约
        BlAppointment queryAppointment = new BlAppointment();
        queryAppointment.setUserId(userId);
        queryAppointment.setWarehouseId(newAppointment.getWarehouseId());
        List<BlAppointment> existingAppointments = appointmentService.selectBlAppointmentList(queryAppointment);
        
        if (existingAppointments == null || existingAppointments.isEmpty()) {
            return null; // 没有冲突
        }
        
        // 检查是否有未取消的预约冲突
        for (BlAppointment existing : existingAppointments) {
            if (existing.getStatus() != null && existing.getStatus() != 2) { // 排除已取消的预约
                if (isDateConflict(existing, newAppointment)) {
                    return error("您已在该仓库的相同日期和时间段有预约记录，不能重复预约");
                }
            }
        }
        
        return null; // 没有冲突
    }
    
    /**
     * 检查日期和时间冲突
     */
    private boolean isDateConflict(BlAppointment existing, BlAppointment newAppointment) {
        // 检查预约日期是否相同
        if (existing.getVisitDate() != null && newAppointment.getVisitDate() != null) {
            // 将 java.util.Date 转换为 java.time.LocalDate 进行比较
            LocalDate existingDate = existing.getVisitDate().toInstant()
                .atZone(java.time.ZoneId.systemDefault())
                .toLocalDate();
            LocalDate newDate = newAppointment.getVisitDate().toInstant()
                .atZone(java.time.ZoneId.systemDefault())
                .toLocalDate();
            
            if (existingDate.equals(newDate)) {
                // 如果预约日期相同，检查预约时间是否冲突
                if (existing.getVisitTime() != null && newAppointment.getVisitTime() != null) {
                    return isTimeConflict(existing.getVisitTime(), newAppointment.getVisitTime());
                } else {
                    // 如果预约时间相同或未设置，则不允许重复预约
                    return true;
                }
            }
        }
        return false;
    }
    
    /**
     * 检查预约时间是否冲突
     * 假设预约时间间隔为1小时，如果两个时间相差小于1小时则认为冲突
     */
    private boolean isTimeConflict(String time1, String time2) {
        try {
            if (time1 == null || time2 == null) {
                return false;
            }
            
            // 解析时间格式（支持 HH:mm 和 HH:mm:ss）
            String[] parts1 = time1.split(":");
            String[] parts2 = time2.split(":");
            
            if (parts1.length < 2 || parts2.length < 2) {
                return false;
            }
            
            int hour1 = Integer.parseInt(parts1[0]);
            int minute1 = Integer.parseInt(parts1[1]);
            int hour2 = Integer.parseInt(parts2[0]);
            int minute2 = Integer.parseInt(parts2[1]);
            
            // 转换为分钟数进行比较
            int totalMinutes1 = hour1 * 60 + minute1;
            int totalMinutes2 = hour2 * 60 + minute2;
            
            // 如果时间差小于60分钟（1小时），则认为冲突
            return Math.abs(totalMinutes1 - totalMinutes2) < 60;
        } catch (Exception e) {
            logger.warn("时间格式解析失败: {} vs {}", time1, time2, e);
            return false;
        }
    }
    
    /**
     * 获取预约列表
     */
    @Anonymous
    @ApiOperation("获取预约列表")
    @GetMapping("/list")
    public TableDataInfo getAppointmentList(
            @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
            @ApiParam("页大小") @RequestParam(defaultValue = "10") Integer pageSize,
            @ApiParam("状态") @RequestParam(required = false) Integer status) {
        
        try {
            // 获取当前用户ID（拦截器已验证token）
            Long userId = getCurrentUserId();
            
            startPage();
            BlAppointment appointment = new BlAppointment();
            appointment.setUserId(userId);
            if (status != null) {
                appointment.setStatus(status);
            }
            
            List<BlAppointmentVo> list = appointmentService.selectBlAppointmentVoList(appointment);
            return getDataTable(list);
        } catch (Exception e) {
            logger.error("获取预约列表失败", e);
            throw new RuntimeException("获取预约列表失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据仓库ID获取用户在仓库的预约
     */
    @Anonymous
    @ApiOperation("根据仓库ID获取用户在仓库的预约")
    @GetMapping("/warehouse/{warehouseId}")
    public AjaxResult getAppointmentByWarehouse(
            @ApiParam("仓库ID") @PathVariable @NotNull(message = "仓库ID不能为空") Long warehouseId) {
        
        try {
            // 获取当前用户ID（拦截器已验证token）
            Long userId = getCurrentUserId();
            
            // 查询用户在指定仓库的预约，过滤掉状态为2（已取消）的记录
            BlAppointment queryAppointment = new BlAppointment();
            queryAppointment.setUserId(userId);
            queryAppointment.setWarehouseId(warehouseId);
            
            List<BlAppointment> appointments = appointmentService.selectBlAppointmentList(queryAppointment);
            
            // 过滤掉已取消的预约
            if (appointments != null) {
                appointments = appointments.stream()
                    .filter(appointment -> appointment.getStatus() == null || appointment.getStatus() != 2)
                    .collect(Collectors.toList());
            }
            
            if (appointments == null || appointments.isEmpty()) {
                return success("暂无预约记录");
            }
            
            return success(appointments);
        } catch (Exception e) {
            logger.error("获取预约记录失败", e);
            return error("获取预约记录失败：" + e.getMessage());
        }
    }
    
    /**
     * 取消预约
     */
    @Anonymous
    @ApiOperation("取消预约")
    @PutMapping("/cancel/{id}")
    public AjaxResult cancelAppointment(
            @ApiParam("预约ID") @PathVariable @NotNull(message = "预约ID不能为空") Long id) {
        try {
            // 获取当前用户ID（拦截器已验证token）
            Long userId = getCurrentUserId();
            
            // 验证预约是否属于当前用户
            BlAppointment existingAppointment = appointmentService.selectBlAppointmentByAppointmentId(id);
            if (existingAppointment == null) {
                return error("预约不存在");
            }
            if (!existingAppointment.getUserId().equals(userId)) {
                return error("无权操作此预约");
            }
            
            // 检查预约状态
            if (existingAppointment.getStatus() != null && existingAppointment.getStatus() == 2) {
                return error("该预约已取消");
            }
            
            BlAppointment appointment = new BlAppointment();
            appointment.setAppointmentId(id);
            appointment.setStatus(2); // 设置为取消状态
            
            int result = appointmentService.updateBlAppointment(appointment);
            if (result > 0) {
                return success("取消预约成功");
            } else {
                return error("取消预约失败，请稍后重试");
            }
        } catch (Exception e) {
            logger.error("取消预约失败", e);
            return error("取消预约失败：" + e.getMessage());
        }
    }
    /**
     * 获取中文星期名称
     */
    private String getChineseDayOfWeek(DayOfWeek dayOfWeek) {
        switch (dayOfWeek) {
            case MONDAY:
                return "星期一";
            case TUESDAY:
                return "星期二";
            case WEDNESDAY:
                return "星期三";
            case THURSDAY:
                return "星期四";
            case FRIDAY:
                return "星期五";
            case SATURDAY:
                return "星期六";
            case SUNDAY:
                return "星期日";
            default:
                return dayOfWeek.toString();
        }
    }
} 